package com.ido.news.splashlibrary.view

import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import api.download.API_DownloadMgr
import api.txSplash.Splash_API_BD
import api.txSplash.Splash_API_KS
import api.txSplash.Splash_API_TT
import api.txSplash.Splash_API_TX
import api.webview.API_WebView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.dotools.umlibrary.UMPostUtils
import com.dotools.utils.NetWorkUtils
import com.dotools.utils.PackageUtils
import com.ido.news.splashlibrary.R
import com.ido.news.splashlibrary.contract.SplashContract
import com.ido.news.splashlibrary.presenter.BaseSplashPresenterImpl
import com.ido.news.splashlibrary.util.Constant
import java.io.File


class SplashView(private val splashBuilder: SplashViewBuilder) : SplashContract.BaseSplashView {
    private val delayTime = 1000   // 每隔1000 毫秒执行一次
    private var duration: Int = 6
    private val mHandler = Handler(Looper.getMainLooper())
    private lateinit var mSkipBtn: TextView
    private lateinit var mSpView: View
    private lateinit var mInflater: LayoutInflater
    private lateinit var mAppIcon: ImageView
    private lateinit var mAppName: TextView
    private lateinit var mGGImg: ImageView
    private lateinit var mIdoImg: ImageView
    private lateinit var mBottomLayout: LinearLayout
    private lateinit var mOtherLayout: FrameLayout
    private var isSkip = false
    private var mStateStr: String = Constant.SplashSuccess
    private var presenter: BaseSplashPresenterImpl? = null
    private var target: Target<Drawable>? = null


    private val timerRunnable = object : Runnable {
        override fun run() {
            if (0 == duration) {
                callBack(mStateStr)
                return
            } else {
                setDuration(--duration)
            }
            mHandler.postDelayed(this, delayTime.toLong())
        }
    }

    private fun setDuration(duration: Int) {
        this.duration = duration
        mSkipBtn.text = String.format("跳过 %d", duration)
    }

    init {
        initView()
    }

    private fun initView() {
        if (presenter == null) {
            presenter = BaseSplashPresenterImpl()
        }
        mInflater = LayoutInflater.from(splashBuilder.context)
        mSpView = mInflater.inflate(R.layout.splash_layout, null)
        mAppIcon = mSpView.findViewById(R.id.bottom_appIcon)
        mAppIcon.setImageBitmap(PackageUtils.getAppIcon(getContext(), getContext().packageName))
        mGGImg = mSpView.findViewById(R.id.GGImg)
        mIdoImg = mSpView.findViewById(R.id.idoImg)
        mAppName = mSpView.findViewById(R.id.bottom_appName)
        mSkipBtn = mSpView.findViewById(R.id.skipText)
        mBottomLayout = mSpView.findViewById(R.id.bottomLayout)
        mOtherLayout = mSpView.findViewById(R.id.otherLayout)
        setSkipBtn()
        setDefaultBg()
        mAppName.text = PackageUtils.getAppName(getContext())
        if (!splashBuilder.isShowIcon) {
            mIdoImg.visibility = View.GONE
            mAppName.visibility = View.VISIBLE
        } else {
            mIdoImg.visibility = View.VISIBLE
        }
        presenter?.onAttach(this)
        splashBuilder.viewGroup.addView(mSpView)
    }

    private fun setSkipBtn() {
        mSkipBtn.setOnClickListener {
            isSkip = true
            UMPostUtils.onEvent(getContext(), "flash_skip")
            callBack(Constant.SplashSkip)
        }
    }

    private fun callBack(msg: String) {
       if(splashBuilder.callBack!=null){
           mHandler.removeCallbacks(timerRunnable)
           when (msg) {
               Constant.SplashSuccess -> {
                   splashBuilder.callBack?.onSuccess()
               }
               Constant.SplashFail -> {
                   splashBuilder.callBack?.onFailed()
               }
               Constant.SplashClick -> {
                   splashBuilder.callBack?.onClick()
               }
               Constant.SplashSkip -> {
                   splashBuilder.callBack?.onSkip()
               }
           }
           detach()
       }
    }

    private fun detach() {
        try {
            mOtherLayout.removeAllViews()
            presenter?.onDetach()
            mHandler.removeCallbacksAndMessages(null)
            splashBuilder.clean()
        } catch (e: Exception) {
            e.printStackTrace()
            val stackTraceElement = e.stackTrace[0]// 得到异常棧的首个元素
            val map = HashMap<String, String>()
            map["detachError"] = "File=" + stackTraceElement.fileName + "-" + "Line=" + stackTraceElement.lineNumber + "-" + "Method=" + stackTraceElement.methodName
            UMPostUtils.onEventMap(getContext(), "flash_failed", map)
        }
    }


    fun show() {
        if (NetWorkUtils.isNetworkAvailable(getContext())) {
            UMPostUtils.onEvent(getContext(), "flash_start")
            presenter!!.getResponse()
            mHandler.post(timerRunnable)
        } else {
            UMPostUtils.onEvent(getContext(), "no_internet")
            Log.e(Constant.Tag, "No NetWork")
            callBack(Constant.SplashFail)
        }
    }


    override fun showOtherSDK(flag: String, showMode: Int, downloadMode: Int) {
        var isClick = false
        when (flag) {
            Constant.TX, Constant.FIRST_TX -> {
                val TXAPI = Splash_API_TX.getInstance()
                if (TXAPI != null) {
                    if (!splashBuilder.txNativePosID.isNullOrEmpty()) {
                        TXAPI.SplashTx(
                            mOtherLayout,
                            splashBuilder.txNativePosID,
                            object : Splash_API_TX.SplashListener {


                                override fun onLoaded() {
                                    UMPostUtils.onEvent(getContext(), "gdt_pullsucceed")
                                }

                                override fun onPresent() {
                                    mHandler.removeCallbacks(timerRunnable)
                                    setBottomLayout()
                                }

                                override fun onDismissed() {
                                    UMPostUtils.onEvent(getContext(), "gdt_show")
                                    if (!isClick && !isSkip) {
                                        callBack(Constant.SplashSuccess)
                                    }
                                }

                                override fun onFailed(code: String, msg: String) {
                                    Log.e(Constant.Tag, "GDTFail:$code:$msg")
                                    val map = HashMap<String, String>()
                                    map["error"] = "$code:$msg"
                                    UMPostUtils.onEventMap(getContext(), "gdt_pullfailed", map)
                                    /**
                                     * 6000:未知错误，详细码：102006
                                     * 3003:网络类型错误，当前设备的网络类型不符合开屏广告的加载条件
                                     * 5004:没有广告
                                     * 5001:服务端数据错误
                                     */
//                            when (code) {
//                                "2001",
//                                "5001",
//                                "5004",
//                                "3003",
//                                "6000" -> {
                                    if (duration >= 2) {
                                        presenter?.SDKFail()
                                    } else {
                                        onError("GdtFail Time is less than 2 seconds")
                                    }
//                                }
//                                else -> {
//                                    onError("GdtFail  Other")
//                                }
//                            }
                                }

                                override fun onClick() {
                                    isClick = true
                                    UMPostUtils.onEvent(getContext(), "gdt_click")
                                    mHandler.postDelayed({
                                        Log.e(Constant.Tag, "onClick")
                                        callBack(Constant.SplashClick)
                                    }, 500)
                                }
                            })
                    } else {
                        Log.e(Constant.Tag, "No GDT PosID")
                        presenter?.SDKFail()
                    }
                } else {
                    Log.e(Constant.Tag, "No GDT SDK")
                    presenter?.SDKFail()
                }
            }
            Constant.TOUTIAO -> {
                val TTAPI = Splash_API_TT.getInstance()
                if (TTAPI != null) {
                    if (!splashBuilder.ttNativePosID.isNullOrEmpty()) {
                        TTAPI.LoadSplash(
                            getContext(),
                            splashBuilder.ttAppId,
                            splashBuilder.ttNativePosID,
                            showMode,
                            downloadMode,
                            splashBuilder.isClickEye,
                            splashBuilder.clickEyePosition,
                            object : Splash_API_TT.SplashListener {
                                override fun onLoaded(view: View?) {
                                    UMPostUtils.onEvent(getContext(), "jrtt_pullsucceed")
                                    mSkipBtn.visibility = View.GONE
                                    mHandler.removeCallbacks(timerRunnable)
                                    setBottomLayout()
                                    mOtherLayout.removeAllViews()
                                    mOtherLayout.addView(view)
                                }

                                override fun onShow(view: View?, type: Int) {
                                    UMPostUtils.onEvent(getContext(), "jrtt_show")
                                }

                                override fun onError(code: Int, message: String?) {
                                    Log.e(Constant.Tag, "JRTTError:$code $message")
                                    val map = HashMap<String, String>()
                                    map["error"] = "$code:$message"
                                    UMPostUtils.onEventMap(getContext(), "jrtt_pullfaild", map)
                                    if (duration >= 2) {
                                        presenter?.SDKFail()
                                    } else {
                                        onError("JRTTFail Time is less than 2 seconds")
                                    }
                                }

                                override fun onTimeout() {
                                    UMPostUtils.onEvent(getContext(), "jrtt_timeout")
                                    onError("jrtt_timeout")
                                }

                                override fun onClicked(view: View?, type: Int) {
                                    UMPostUtils.onEvent(getContext(), "jrtt_click")
                                    isClick = true
                                    mHandler.postDelayed({
                                        callBack(Constant.SplashClick)
                                    }, 500)
                                }

                                override fun onSkip() {
                                    UMPostUtils.onEvent(getContext(), "jrtt_skip")
                                    callBack(Constant.SplashSkip)
                                }

                                override fun onTimeOver() {
                                    if (!isClick && !isSkip) {
                                        callBack(Constant.SplashSuccess)
                                    }
                                }
                            })
                    }else {
                        Log.e(Constant.Tag, "No JRTT PosID")
                        presenter?.SDKFail()
                    }
                } else {
                    Log.e(Constant.Tag, "No JRTT SDK")
                    presenter?.SDKFail()
                }
            }
            Constant.BD -> {
                val BDAPI = Splash_API_BD.getInstance()
                if (BDAPI != null) {
                    BDAPI.LoadSplash(
                        mOtherLayout,
                        splashBuilder.bdAppId,
                        splashBuilder.bdNativePosID,
                        object : Splash_API_BD.SplashListener {
                            override fun onPresent() {
                                UMPostUtils.onEvent(getContext(), "bd_pullsucceed")
                                mHandler.removeCallbacks(timerRunnable)
                                setBottomLayout()
                            }

                            override fun onDismissed() {
                                if (!isClick && !isSkip) {
                                    callBack(Constant.SplashSuccess)
                                }
                            }

                            override fun onLpClosed() {
                            }

                            override fun onFailed(msg: String?) {
                                val map = HashMap<String, String>()
                                map["error"] = "$msg"
                                UMPostUtils.onEventMap(getContext(), "bd_pullfailed", map)
                                if (duration >= 2) {
                                    presenter?.SDKFail()
                                } else {
                                    onError("BDFail Time is less than 2 seconds")
                                }
                            }

                            override fun onClick() {
                                isClick = true
                                UMPostUtils.onEvent(getContext(), "bd_click")
                                mHandler.postDelayed({
                                    Log.e(Constant.Tag, "onClick")
                                    callBack(Constant.SplashClick)
                                }, 500)
                            }
                        })
                } else {
                    presenter?.SDKFail()
                }
            }
            Constant.KS -> {
                val KSAPI = Splash_API_KS.getInstance()
                if (KSAPI != null) {
                    KSAPI.loadSplashKS(
                        mOtherLayout,
                        splashBuilder.ksNativePosID,
                        object : Splash_API_KS.SplashListener {
                            override fun onLoaded() {
                                mSkipBtn.visibility = View.GONE
                                UMPostUtils.onEvent(getContext(), "ks_pullsucceed")
                            }

                            override fun onPresent() {
                                UMPostUtils.onEvent(getContext(), "ks_show")
                                mHandler.removeCallbacks(timerRunnable)
                                setBottomLayout()
                            }

                            override fun onDismissed() {
                                if (!isClick && !isSkip) {
                                    callBack(Constant.SplashSuccess)
                                }
                            }

                            override fun onFailed(code: Int, msg: String) {
                                Log.e(Constant.Tag, "KSError:$code $msg")
                                val map = HashMap<String, String>()
                                map["error"] = "$code:$msg"
                                UMPostUtils.onEventMap(getContext(), "ks_pullfailed", map)
                                if (duration >= 2) {
                                    presenter?.SDKFail()
                                } else {
                                    onError("KSFail Time is less than 2 seconds")
                                }
                            }

                            override fun onSkipped() {
                                callBack(Constant.SplashSkip)
                            }

                            override fun onClick() {
                                isClick = true
                                UMPostUtils.onEvent(getContext(), "ks_click")
                                mHandler.postDelayed({
                                    Log.e(Constant.Tag, "onClick")
                                    callBack(Constant.SplashClick)
                                }, 500)
                            }

                            override fun onDownloadTipsShow() {
                                UMPostUtils.onEvent(getContext(), "ks_download_tip_show")
                            }

                            override fun onDownloadTipsDismiss() {
                                UMPostUtils.onEvent(getContext(), "ks_download_tip_dismiss")
                                if (isClick && !isSkip) {
                                    callBack(Constant.SplashSuccess)
                                }
                            }

                            override fun onDownloadTipsCancel() {
                                UMPostUtils.onEvent(getContext(), "ks_download_tip_cancel")
                            }
                        })
                } else {
                    presenter?.SDKFail()
                }
            }
        }
    }

    override fun showImg(url: String, id: String) {
        target = Glide.with(getContext()).load(url).listener(object : RequestListener<Drawable> {
            override fun onLoadFailed(
                e: GlideException?,
                model: Any?,
                target: Target<Drawable>?,
                isFirstResource: Boolean
            ): Boolean {
                Log.e(Constant.Tag, getContext().getString(R.string.loadimgerror).toString())
                onError("flash_ziying_failed")
                return false
            }

            override fun onResourceReady(
                resource: Drawable?,
                model: Any?,
                target: Target<Drawable>?,
                dataSource: DataSource?,
                isFirstResource: Boolean
            ): Boolean {
                mSkipBtn.visibility = View.VISIBLE
                mIdoImg.visibility = View.GONE
                setSkipBtn()
                setBottomLayout()
                val map = HashMap<String, String>()
                map["AdId"] = id
                UMPostUtils.onEventMap(getContext(), "flash_show", map)
                try {
                    if (resource !is BitmapDrawable) {
                        val drawable: GifDrawable? = resource as GifDrawable?
                        drawable?.setLoopCount(1)
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    //是普通图片
                }
                mStateStr = Constant.SplashSuccess
                return false
            }
        }).into(mGGImg)
    }

    override fun setDownloadClick(
        fileUrl: String,
        titleName: String,
        packageName: String,
        iconUrl: String,
        index: Int,
        id: String
    ) {
        mGGImg.setOnClickListener {
            val map = HashMap<String, String>()
            map[index.toString()] = id
            UMPostUtils.onEventMap(getContext(), "flash_click", map)
            callBack(Constant.SplashClick)
            if (API_DownloadMgr.getInstance() != null) {
                val dPath = Environment.getExternalStorageDirectory()
                    .toString() + (File.separator + "IBOX/download/")
                val file = File(dPath)
                if (!file.exists()) {
                    file.mkdirs()
                }
                val dName =
                    dPath + packageName + "_" + (System.currentTimeMillis() / 1000).toString() + ".apk"
                API_DownloadMgr.getInstance().addNewDownload(
                    fileUrl,
                    titleName,
                    dName,
                    packageName,
                    iconUrl,
                    true,
                    null,
                    API_DownloadMgr.DL_TYPE.Flash,
                    getContext()
                )
            } else {
                NetWorkUtils.startBrowserByRI( getContext(), fileUrl)
            }
        }

    }

    override fun setOpenClick(url: String, index: Int, id: String) {
        mGGImg.setOnClickListener {
            val map = HashMap<String, String>()
            map[index.toString()] = id
            UMPostUtils.onEventMap(getContext(), "flash_click", map)
            callBack(Constant.SplashClick)
            if (API_WebView.getInstance() != null) {
                API_WebView.getInstance().startWebViewActivity( getContext(), url)
            } else {
                NetWorkUtils.startBrowserByRI(getContext(), url)
            }
        }
    }

    override fun getContext(): Context {
        return splashBuilder.context!!.applicationContext
    }


    override fun onError(msg: String) {
        Log.e(Constant.Tag, msg)
        val map = HashMap<String, String>()
        map["error"] = msg
        UMPostUtils.onEventMap(getContext(), "flash_failed", map)
        callBack(Constant.SplashFail)
    }

    private fun setBottomLayout() {
        if (splashBuilder.isFullShow) {
            mBottomLayout.visibility = View.GONE
        }
    }

    private fun setDefaultBg() {
        if (splashBuilder.defaultBgResId != null) {
            mGGImg.setBackgroundResource(splashBuilder.defaultBgResId)
        }
    }

}